allwinner: Introduce basic platform support
authorSamuel Holland <[email protected]>
Sat, 12 Aug 2017 09:07:39 +0000 (04:07 -0500)
committerAndre Przywara <[email protected]>
Fri, 15 Jun 2018 10:45:24 +0000 (11:45 +0100)
This platform supports Allwinner's SoCs with ARMv8 cores. So far they
all sport a single cluster of Cortex-A53 cores.

"sunxi" is the original code name used for this platform, and since it
appears in the Linux kernel and in U-Boot as well, we use it here as a
short file name prefix and for identifiers.

This port includes BL31 support only. U-Boot's SPL takes the role of the
primary loader, also doing the DRAM initialization. It then loads the
rest of the firmware, namely ATF and U-Boot (BL33), then hands execution
over to ATF.

This commit includes the basic platform code shared across all SoCs.
There is no platform.mk yet.

[Andre: moved files into proper directories, supported RESET_TO_BL31,
various clean ups and simplifications ]

Signed-off-by: Samuel Holland <[email protected]>
Signed-off-by: Andre Przywara <[email protected]>
plat/allwinner/common/include/plat_macros.S [new file with mode: 0644]
plat/allwinner/common/include/platform_def.h [new file with mode: 0644]
plat/allwinner/common/include/sunxi_def.h [new file with mode: 0644]
plat/allwinner/common/plat_helpers.S [new file with mode: 0644]
plat/allwinner/common/sunxi_bl31_setup.c [new file with mode: 0644]
plat/allwinner/common/sunxi_common.c [new file with mode: 0644]
plat/allwinner/common/sunxi_pm.c [new file with mode: 0644]
plat/allwinner/common/sunxi_private.h [new file with mode: 0644]
plat/allwinner/common/sunxi_topology.c [new file with mode: 0644]

diff --git a/plat/allwinner/common/include/plat_macros.S b/plat/allwinner/common/include/plat_macros.S
new file mode 100644 (file)
index 0000000..6ee4597
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_MACROS_S__
+#define __PLAT_MACROS_S__
+
+#include <arm_macros.S>
+#include <sunxi_mmap.h>
+
+       /* ---------------------------------------------
+        * The below required platform porting macro
+        * prints out relevant GIC and CCI registers
+        * whenever an unhandled exception is taken in
+        * BL31.
+        * Clobbers: x0 - x10, x16, x17, sp
+        * ---------------------------------------------
+        */
+       .macro plat_crash_print_regs
+       mov_imm x17, SUNXI_GICC_BASE
+       mov_imm x16, SUNXI_GICD_BASE
+       arm_print_gic_regs
+       .endm
+
+#endif /* __PLAT_MACROS_S__ */
diff --git a/plat/allwinner/common/include/platform_def.h b/plat/allwinner/common/include/platform_def.h
new file mode 100644 (file)
index 0000000..ca7db2f
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+#include <common_def.h>
+#include <sunxi_mmap.h>
+#include <tbbr/tbbr_img_def.h>
+
+#define BL31_BASE                      SUNXI_SRAM_A2_BASE
+#define BL31_LIMIT                     (SUNXI_SRAM_A2_BASE + SUNXI_SRAM_A2_SIZE)
+
+/* The traditional U-Boot load address is 160MB into DRAM, so at 0x4a000000 */
+#define PLAT_SUNXI_NS_IMAGE_OFFSET     (SUNXI_DRAM_BASE + (160U << 20))
+
+#define CACHE_WRITEBACK_SHIFT          6
+#define CACHE_WRITEBACK_GRANULE                (1 << CACHE_WRITEBACK_SHIFT)
+
+#define MAX_MMAP_REGIONS               (4 + PLATFORM_MMAP_REGIONS)
+#define MAX_XLAT_TABLES                        2
+
+#define PLAT_MAX_PWR_LVL_STATES                2
+#define PLAT_MAX_RET_STATE             1
+#define PLAT_MAX_OFF_STATE             2
+
+#define PLAT_MAX_PWR_LVL               2
+#define PLAT_NUM_PWR_DOMAINS           (1 + \
+                                        PLATFORM_CLUSTER_COUNT + \
+                                        PLATFORM_CORE_COUNT)
+
+#define PLAT_PHY_ADDR_SPACE_SIZE       (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE      (1ULL << 32)
+
+#define PLATFORM_CLUSTER_COUNT         1
+#define PLATFORM_CORE_COUNT            (PLATFORM_CLUSTER_COUNT * \
+                                        PLATFORM_MAX_CPUS_PER_CLUSTER)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER  4
+#define PLATFORM_MMAP_REGIONS          4
+#define PLATFORM_STACK_SIZE            (0x1000 / PLATFORM_CORE_COUNT)
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/allwinner/common/include/sunxi_def.h b/plat/allwinner/common/include/sunxi_def.h
new file mode 100644 (file)
index 0000000..e68fbe4
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SUNXI_DEF_H__
+#define __SUNXI_DEF_H__
+
+/* Clock configuration */
+#define SUNXI_OSC24M_CLK_IN_HZ         24000000
+
+/* UART configuration */
+#define SUNXI_UART0_BAUDRATE           115200
+#define SUNXI_UART0_CLK_IN_HZ          SUNXI_OSC24M_CLK_IN_HZ
+
+#endif /* __SUNXI_DEF_H__ */
diff --git a/plat/allwinner/common/plat_helpers.S b/plat/allwinner/common/plat_helpers.S
new file mode 100644 (file)
index 0000000..b00c7ae
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <sunxi_def.h>
+#include <sunxi_mmap.h>
+
+       .globl  plat_crash_console_init
+       .globl  plat_crash_console_putc
+       .globl  plat_crash_console_flush
+       .globl  plat_my_core_pos
+       .globl  platform_mem_init
+       .globl  plat_report_exception
+
+func plat_crash_console_init
+       mov_imm x0, SUNXI_UART0_BASE
+       mov_imm x1, SUNXI_UART0_CLK_IN_HZ
+       mov_imm x2, SUNXI_UART0_BAUDRATE
+       b       console_16550_core_init
+endfunc plat_crash_console_init
+
+func plat_crash_console_putc
+       mov_imm x1, SUNXI_UART0_BASE
+       b       console_16550_core_putc
+endfunc plat_crash_console_putc
+
+func plat_crash_console_flush
+       ret
+endfunc plat_crash_console_flush
+
+func plat_my_core_pos
+       mrs     x0, mpidr_el1
+       and     x1, x0, #MPIDR_CLUSTER_MASK
+       and     x0, x0, #MPIDR_CPU_MASK
+       add     x0, x0, x1, LSR #6
+       ret
+endfunc plat_my_core_pos
+
+func platform_mem_init
+       ret
+endfunc platform_mem_init
+
+func plat_report_exception
+       ret
+endfunc plat_report_exception
diff --git a/plat/allwinner/common/sunxi_bl31_setup.c b/plat/allwinner/common/sunxi_bl31_setup.c
new file mode 100644 (file)
index 0000000..6331238
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <assert.h>
+#include <console.h>
+#include <debug.h>
+#include <generic_delay_timer.h>
+#include <gicv2.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <sunxi_def.h>
+#include <sunxi_mmap.h>
+#include <uart_16550.h>
+
+#include "sunxi_private.h"
+
+static entry_point_info_t bl33_image_ep_info;
+
+static console_16550_t console;
+
+static const gicv2_driver_data_t sunxi_gic_data = {
+       .gicd_base = SUNXI_GICD_BASE,
+       .gicc_base = SUNXI_GICC_BASE,
+};
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+                               u_register_t arg2, u_register_t arg3)
+{
+       /* Initialize the debug console as soon as possible */
+       console_16550_register(SUNXI_UART0_BASE, SUNXI_UART0_CLK_IN_HZ,
+                              SUNXI_UART0_BAUDRATE, &console);
+
+       /* Populate entry point information for BL33 */
+       SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
+       /*
+        * Tell BL31 where the non-trusted software image
+        * is located and the entry state information
+        */
+       bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+       bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
+                                         DISABLE_ALL_EXCEPTIONS);
+       SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+}
+
+void bl31_plat_arch_setup(void)
+{
+       sunxi_configure_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+       generic_delay_timer_init();
+
+       /* Configure the interrupt controller */
+       gicv2_driver_init(&sunxi_gic_data);
+       gicv2_distif_init();
+       gicv2_pcpu_distif_init();
+       gicv2_cpuif_enable();
+
+       INFO("BL31: Platform setup done\n");
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+       assert(sec_state_is_valid(type) != 0);
+       assert(type == NON_SECURE);
+
+       return &bl33_image_ep_info;
+}
diff --git a/plat/allwinner/common/sunxi_common.c b/plat/allwinner/common/sunxi_common.c
new file mode 100644 (file)
index 0000000..e36c8b0
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform.h>
+#include <platform_def.h>
+#include <sunxi_def.h>
+#include <xlat_tables_v2.h>
+
+static mmap_region_t sunxi_mmap[PLATFORM_MMAP_REGIONS + 1] = {
+       MAP_REGION_FLAT(SUNXI_ROM_BASE, SUNXI_ROM_SIZE,
+                       MT_MEMORY | MT_RO | MT_SECURE),
+       MAP_REGION_FLAT(SUNXI_SRAM_BASE, SUNXI_SRAM_SIZE,
+                       MT_MEMORY | MT_RW | MT_SECURE),
+       MAP_REGION_FLAT(SUNXI_DEV_BASE, SUNXI_DEV_SIZE,
+                       MT_DEVICE | MT_RW | MT_SECURE),
+       MAP_REGION_FLAT(SUNXI_DRAM_BASE, SUNXI_DRAM_SIZE,
+                       MT_MEMORY | MT_RW | MT_NS),
+       {},
+};
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+       return SUNXI_OSC24M_CLK_IN_HZ;
+}
+
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+#ifdef PRELOADED_BL33_BASE
+       return PRELOADED_BL33_BASE;
+#else
+       return PLAT_SUNXI_NS_IMAGE_OFFSET;
+#endif
+}
+
+void sunxi_configure_mmu_el3(int flags)
+{
+       mmap_add_region(BL31_BASE, BL31_BASE,
+                       BL31_LIMIT - BL31_BASE,
+                       MT_MEMORY | MT_RW | MT_SECURE);
+       mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
+                       BL_CODE_END - BL_CODE_BASE,
+                       MT_CODE | MT_SECURE);
+       mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE,
+                       BL_RO_DATA_END - BL_RO_DATA_BASE,
+                       MT_RO_DATA | MT_SECURE);
+       mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE,
+                       BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
+                       MT_DEVICE | MT_RW | MT_SECURE);
+       mmap_add(sunxi_mmap);
+       init_xlat_tables();
+
+       enable_mmu_el3(0);
+}
diff --git a/plat/allwinner/common/sunxi_pm.c b/plat/allwinner/common/sunxi_pm.c
new file mode 100644 (file)
index 0000000..c73400e
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <delay_timer.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <psci.h>
+#include <sunxi_mmap.h>
+
+#define SUNXI_WDOG0_CTRL_REG           (SUNXI_WDOG_BASE + 0x0010)
+#define SUNXI_WDOG0_CFG_REG            (SUNXI_WDOG_BASE + 0x0014)
+#define SUNXI_WDOG0_MODE_REG           (SUNXI_WDOG_BASE + 0x0018)
+
+static void __dead2 sunxi_system_off(void)
+{
+       ERROR("PSCI: Full shutdown not implemented, halting\n");
+       wfi();
+       panic();
+}
+
+static void __dead2 sunxi_system_reset(void)
+{
+       /* Reset the whole system when the watchdog times out */
+       mmio_write_32(SUNXI_WDOG0_CFG_REG, 1);
+       /* Enable the watchdog with the shortest timeout (0.5 seconds) */
+       mmio_write_32(SUNXI_WDOG0_MODE_REG, (0 << 4) | 1);
+       /* Wait for twice the watchdog timeout before panicking */
+       mdelay(1000);
+
+       ERROR("PSCI: System reset failed\n");
+       wfi();
+       panic();
+}
+
+static plat_psci_ops_t sunxi_psci_ops = {
+       .system_off                     = sunxi_system_off,
+       .system_reset                   = sunxi_system_reset,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+                       const plat_psci_ops_t **psci_ops)
+{
+       assert(psci_ops);
+
+       *psci_ops = &sunxi_psci_ops;
+
+       return 0;
+}
diff --git a/plat/allwinner/common/sunxi_private.h b/plat/allwinner/common/sunxi_private.h
new file mode 100644 (file)
index 0000000..34e5639
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SUNXI_PRIVATE_H__
+#define __SUNXI_PRIVATE_H__
+
+void sunxi_configure_mmu_el3(int flags);
+
+#endif /* __SUNXI_PRIVATE_H__ */
diff --git a/plat/allwinner/common/sunxi_topology.c b/plat/allwinner/common/sunxi_topology.c
new file mode 100644 (file)
index 0000000..98cf63c
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <platform.h>
+#include <platform_def.h>
+
+static unsigned char plat_power_domain_tree_desc[PLAT_MAX_PWR_LVL + 1] = {
+       /* One root node for the SoC */
+       1,
+       /* One node for each cluster */
+       PLATFORM_CLUSTER_COUNT,
+       /* One set of CPUs per cluster */
+       PLATFORM_MAX_CPUS_PER_CLUSTER,
+};
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+       unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr);
+       unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
+
+       if (MPIDR_AFFLVL3_VAL(mpidr) > 0 ||
+           MPIDR_AFFLVL2_VAL(mpidr) > 0 ||
+           cluster >= PLATFORM_CLUSTER_COUNT ||
+           core >= PLATFORM_MAX_CPUS_PER_CLUSTER) {
+               return -1;
+       }
+
+       return cluster * PLATFORM_MAX_CPUS_PER_CLUSTER + core;
+}
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+       return plat_power_domain_tree_desc;
+}